package com.tgh.gles2;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.FrameLayout;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;

public class RendererActivity extends Activity {

    public static final String TAG = "OpenGL ES2";
    protected GLSurfaceView mSurfaceView;
    protected boolean checkOpenGLVersion=true;
    protected boolean mMultisamplingEnabled=false;
    protected boolean mUsesCoverageAa=false;
    protected BaseRenderer mRenderer=null;
    protected FrameLayout mLayout;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        mSurfaceView = new GLSurfaceView(this);
        
        ActivityManager am=(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        if (checkOpenGLVersion) {
            ConfigurationInfo info = am.getDeviceConfigurationInfo();
            if (info.reqGlEsVersion<0x20000) {
                throw new RuntimeException("Opengl 2.0 is not supported by this device");
            }
        }
        
        mSurfaceView.setEGLContextClientVersion(2);
        mLayout = new FrameLayout(this);
        mLayout.addView(mSurfaceView);
        
        if (mMultisamplingEnabled) {
            createMultisampleConfig();
        }
        
        setContentView(mLayout);
    }
    
    protected void createMultisampleConfig() {
        final int EGL_COVERAGE_BUFFERS_NV=0x30E0;
        final int EGL_COVERAGE_SAMPLES_NV=0x30E1;
        
        mSurfaceView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {
            @Override
            public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
                int[] configSpec=new int[]{
                        EGL10.EGL_RED_SIZE, 5,
                        EGL10.EGL_GREEN_SIZE, 6,
                        EGL10.EGL_BLUE_SIZE, 5,
                        EGL10.EGL_DEPTH_SIZE, 16,
                        EGL10.EGL_RENDERABLE_TYPE, 4,
                        EGL10.EGL_SAMPLE_BUFFERS, 1,
                        EGL10.EGL_SAMPLES, 2,
                        EGL10.EGL_NONE
                };
                int[] result=new int[1];
                if (!egl.eglChooseConfig(display, configSpec, null, 0, result)) {
                    Log.e(TAG, "Multisampling configuration 1 failed.");
                }
                
                if (result[0]<=0) {
                    
                    configSpec=new int[]{
                            EGL10.EGL_RED_SIZE, 5,
                            EGL10.EGL_GREEN_SIZE, 6,
                            EGL10.EGL_BLUE_SIZE, 5,
                            EGL10.EGL_DEPTH_SIZE, 16,
                            EGL10.EGL_RENDERABLE_TYPE, 4,
                            EGL_COVERAGE_BUFFERS_NV, 1,
                            EGL_COVERAGE_SAMPLES_NV, 2,
                            EGL10.EGL_NONE
                    };
                    
                    if (!egl.eglChooseConfig(display, configSpec, null, 0, result)) {
                        Log.e(TAG, "Multisampling configuration 2 failed.");
                    }
                    
                    if (result[0]<=0) {
                        configSpec=new int[]{
                                EGL10.EGL_RED_SIZE, 5,
                                EGL10.EGL_GREEN_SIZE, 6,
                                EGL10.EGL_BLUE_SIZE, 5,
                                EGL10.EGL_DEPTH_SIZE, 16,
                                EGL10.EGL_RENDERABLE_TYPE, 4,
                                EGL10.EGL_NONE
                        };
                        
                        if (!egl.eglChooseConfig(display, configSpec, null, 0, result)) {
                            Log.e(TAG, "Multisampling configuration 3 failed. Multisampling is not possible on your divice.");
                        }
                        
                        if (result[0]<=0) {
                            throw new RuntimeException("Couldn't create OpenGL config.");
                        }
                    }else {
                        mUsesCoverageAa=true;
                    }
                }
                EGLConfig[] configs=new EGLConfig[result[0]];
                
                if (!egl.eglChooseConfig(display, configSpec, configs, result[0], result)) {
                    throw new RuntimeException("Couldn't create OpenGL config.");
                }
                int index=-1;
                int[] value=new int[1];
                for (int i = 0; i < configs.length; i++) {
                    egl.eglGetConfigAttrib(display, configs[i], EGL10.EGL_RED_SIZE, value);
                    if (value[0]==5) {
                        index=i;
                        break;
                    }
                }
                EGLConfig config=configs.length>0?configs[index]:null;
                if (config==null) {
                    throw new RuntimeException("No config chosen.");
                }
                
                return config;
            }
        });
    }
    
    protected void setGLBackgroundTransparent(boolean transparent) {
        if (transparent) {
            mSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
            mSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
            mSurfaceView.setZOrderOnTop(true);
        } else {
            mSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
            mSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888);
            mSurfaceView.setZOrderOnTop(false);
        }
    }
    
    protected void setRenderer(BaseRenderer renderer) {
        mRenderer=renderer;
        mSurfaceView.setRenderer(renderer);
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        mSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
        mSurfaceView.onResume();
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        mSurfaceView.onPause();
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mRenderer.onSurfaceDestroyed();
        unbindDrawables(mLayout);
        System.gc();
    }
    
    private void unbindDrawables(View view) {
        if (view.getBackground()!=null) {
            view.getBackground().setCallback(null);
        }
        if (view instanceof ViewGroup && !( view instanceof AdapterView)) {
            ViewGroup vp=(ViewGroup) view;
            for(int i=0;i<vp.getChildCount();i++){
                unbindDrawables(vp.getChildAt(i));
            }
            vp.removeAllViews();
        }
    }
}
